/***************************************************************************
 *   Copyright (C) 2004 by cyril dupuit                                    *
 *   cyrildupuit@hotmail.com                                               *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

/******************************************************************************
* Nom du module : Cpu_a.s
* Description : Ce module est utilise pour realiser les operations bas niveau.
* C'est lui qui gere la commutation de contexte ou encore l'appel au procedure
* haut niveau permettant la gestion du temps noyau, etc...
* niveau du noyau comme son initialisation ou encore l'ordonnancement
******************************************************************************/
 
/* Historique : */
/* 28/10/04 : Creation du module V1.0 */

#define ASM_SOURCE 1
	
#include "idt.h"
	
.file "Cpu_a.S"

.text
.extern InterruptEnter		/*Definit dans le fichier Core.c*/
.extern InterruptExit		/*Definit dans le fichier Core.c*/
.extern TickManager		/*Definit dans le fichier Core.c*/
.extern GetStackMin		/*Definit dans le fichier Core.c*/

.extern CurrentTaskDesc		/*Definit dans le fichier Core.c*/
.extern NextTaskDesc		/*Definit dans le fichier Core.c*/

.globl LoadTask
.globl SwitchTask
.globl TickInt
.globl AsmPageFault
.globl AsmKeyboardVector
.globl AsmMouseVector

/******************************************************************************
* But de la procedure d'it : Charger le contexte d'un thread si le thread
* courant a ete supprime ou si le thread courant est inexistant.
******************************************************************************/
LoadTask:
	leal CurrentTaskDesc, %edi	/* Chargement dans edi de l'adresse de CurrentTaskDesc */
	movl (%edi), %eax		/* eax = CurrentTaskDesc */
	movl (%eax), %esp		/* esp = CurrentTaskDesc->pStack */	
	/* Charger le contexte de la tache */
	popw  %gs
	popw  %fs
	popw  %es
        popw  %ds
	popw  %ss
	addl  $2,%esp
	popl  %eax
	popl  %ebx
	popl  %ecx
	popl  %edx
	popl  %esi
	popl  %edi
	popl  %ebp
	addl $4, %esp
	iret

/******************************************************************************
* But de la procedure d'it : Sauvegarder le contexte du thread courant, definir
* le thread suivant comme thread courant et charger son contexte.
******************************************************************************/
SwitchTask:
	/* Fake error code */
	pushl $0
	/* Backup the context */
	pushl %ebp
	movl %esp, %ebp
	
	pushl %edi
	pushl %esi
	pushl %edx
	pushl %ecx
	pushl %ebx
	pushl %eax
	subl  $2,%esp
	pushw %ss
	pushw %ds
	pushw %es
	pushw %fs
	pushw %gs
	
	/* Sauvegarde de la valeur de la pile dans le descripteur de thread */
	leal CurrentTaskDesc, %edi
	movl (%edi), %eax		/* eax = CurrentTaskDesc */
	movl %esp, (%eax)		/* CurrentTaskDesc->pStack = esp */
	
	/* Definir le thread suivant comme thread courant */
	movl NextTaskDesc, %eax
	movl %eax, CurrentTaskDesc
	/* Restaurer la valeur de la pile */
	leal CurrentTaskDesc, %edi	/* Chargement dans edi de l'adresse de CurrentTaskDesc */
	movl (%edi), %eax		/* eax = CurrentTaskDesc */
	movl (%eax), %esp		/* esp = CurrentTaskDesc->pStack */	
	
	/* Restaurer le contexte du nouveau thread courant */
	popw  %gs
	popw  %fs
	popw  %es
	popw  %ds
	popw  %ss
	addl  $2,%esp
	popl  %eax
	popl  %ebx
	popl  %ecx
	popl  %edx
	popl  %esi
	popl  %edi
	
	popl  %ebp
	/* Remove fake error code */
	addl $4, %esp

	iret

/******************************************************************************
* But de la procedure d'IT : Appeler le gestionnaire de temps du noyau et
* effectuer une mesure de la pile du thread courant.
******************************************************************************/
TickInt :
	/* Fake error code */
	pushl $0
	/* Backup the context */
	pushl %ebp
	movl %esp, %ebp
	pushl %edi
	pushl %esi
	pushl %edx
	pushl %ecx
	pushl %ebx
	pushl %eax
	subl  $2,%esp
	pushw %ss
	pushw %ds
	pushw %es
	pushw %fs
	pushw %gs
	
	/* Acquitter le PIC */
	movb  $0x20, %al
	outb  %al, $0x20
	
	/* Signaler au noyau l'arrivee dans une ISR*/
	call InterruptEnter

	/* Gestionnaire de temps noyau */
	call TickManager

	/* Signaler au noyau la sortie d'une ISR*/
	call InterruptExit
	
	/* Restaurer le contexte de la nouvelle tache courante */
	popw  %gs
	popw  %fs
	popw  %es
	popw  %ds
	popw  %ss
	addl  $2,%esp
	popl  %eax
	popl  %ebx
	popl  %ecx
	popl  %edx
	popl  %esi
	popl  %edi
	popl  %ebp
	/* Remove fake error code */
	addl $4, %esp

	iret

/******************************************************************************
* But de la procedure d'IT : Appeler le gestionnaire de temps du noyau et
* effectuer une mesure de la pile du thread courant.
******************************************************************************/
AsmPageFault :
	pushl %ebp        
	movl %esp, %ebp
		
	pushl %edi        
	pushl %esi        
	pushl %edx        
	pushl %ecx        
	pushl %ebx        
	pushl %eax
	subl  $2,%esp
	pushw %ss
	pushw %ds
	pushw %es
	pushw %fs
	pushw %gs

	
	/* Appeler le gestionnaire du defaut de page */
	pushl %esp
	call  PageFaultVector
	addl  $4, %esp
	
/*	movl %eax, %esp
*/	
	/* Restore the context */
	popw  %gs
	popw  %fs
	popw  %es
	popw  %ds
	popw  %ss
	addl  $2,%esp
	popl  %eax
	popl  %ebx
	popl  %ecx
	popl  %edx
	popl  %esi
	popl  %edi
	popl  %ebp

	/* Error code isn't compatible with iretd */
	addl $4, %esp
	
	iret

/******************************************************************************
* But de la procedure d'IT : Appeler la procedure de gestion du clavier
******************************************************************************/
AsmKeyboardVector:
	/* Fake error code */
	pushl $0
	/* Backup the context */
	pushl %ebp
	movl %esp, %ebp
	pushl %edi
	pushl %esi
	pushl %edx
	pushl %ecx
	pushl %ebx
	pushl %eax
	subl  $2,%esp
	pushw %ss
	pushw %ds
	pushw %es
	pushw %fs
	pushw %gs
	
	/* Acquitter le PIC */
	movb  $0x20, %al
	outb  %al, $0x20
	
	/* Signaler au noyau l'arrivee dans une ISR*/
	call InterruptEnter
	
	/* Appeler la procedure de gestion du clavier */
	call KeyboardVector
	
	/* Signaler au noyau la sortie d'une ISR*/
	call InterruptExit
	
	/* Restaurer le contexte */
	popw  %gs
	popw  %fs
	popw  %es
	popw  %ds
	popw  %ss
	addl  $2,%esp
	popl  %eax
	popl  %ebx
	popl  %ecx
	popl  %edx
	popl  %esi
	popl  %edi
	
	popl  %ebp
	/* Remove fake error code */
	addl $4, %esp
	iret
	
/******************************************************************************
* But de la procedure d'IT : Appeler la procedure de gestion de la souris
******************************************************************************/
AsmMouseVector:
	/* Fake error code */
	pushl $0
	/* Backup the context */
	pushl %ebp
	movl %esp, %ebp
	pushl %edi
	pushl %esi
	pushl %edx
	pushl %ecx
	pushl %ebx
	pushl %eax
	subl  $2,%esp
	pushw %ss
	pushw %ds
	pushw %es
	pushw %fs
	pushw %gs
	
	/* Acquitter le PIC */
/*	movb  $0x20, %al
	outb  %al, $0x20*/
	
	/* Signaler au noyau l'arrivee dans une ISR*/
	call InterruptEnter
	
	/* Appeler la procedure de gestion du clavier */
	call MouseVector
	
	/* Signaler au noyau la sortie d'une ISR*/
	call InterruptExit
	
	/* Restaurer le contexte */
	popw  %gs
	popw  %fs
	popw  %es
	popw  %ds
	popw  %ss
	addl  $2,%esp
	popl  %eax
	popl  %ebx
	popl  %ecx
	popl  %edx
	popl  %esi
	popl  %edi
	
	popl  %ebp
	/* Remove fake error code */
	addl $4, %esp
	iret
	
/*****************************************************************************/
